package com.like.banzipao.server.util.roomstate

import com.like.banzipao.server.model.CompletedOrder
import com.like.banzipao.server.model.Player
import com.like.banzipao.server.model.PlayerState
import com.like.banzipao.server.model.Poker
import com.like.banzipao.server.model.PokerState
import com.like.banzipao.server.model.Room
import com.like.banzipao.server.model.Suit
import com.like.banzipao.server.model.User

interface IRoomState {
    fun contains(user: User): Boolean
    fun contains(userId: Int): Boolean
    fun isFull(): Boolean
    fun isEmpty(): Boolean
    fun addPlayer(user: User)
    fun removePlayer(user: User)
    fun ready(user: User, dealerUserId: Int)
    fun again(user: User)
    fun bao(user: User)
    fun fanBao(user: User)
    fun baoPass(user: User)
    fun fanBaoPass(user: User)
    fun getAllFindFriendPokers(): List<Poker>
    fun findFriend(user: User, id: Int)
    fun drawPlayed(user: User, ids: List<Int>)
    fun drawTake(user: User, ids: List<Int>)
    fun getSpade7(): Poker?
    fun playPlayed(user: User, ids: List<Int>): Boolean
    fun playPass(user: User)
    fun getDealerUserId(): Int
    fun getIntegralChange(player: Player): Int
}

open class RoomStateAdapter : IRoomState {
    override fun contains(user: User): Boolean {
        return false
    }

    override fun contains(userId: Int): Boolean {
        return false
    }

    override fun isFull(): Boolean {
        return false
    }

    override fun isEmpty(): Boolean {
        return false
    }

    override fun addPlayer(user: User) {
    }

    override fun removePlayer(user: User) {
    }

    override fun ready(user: User, dealerUserId: Int) {
    }

    override fun again(user: User) {
    }

    override fun bao(user: User) {
    }

    override fun fanBao(user: User) {
    }

    override fun baoPass(user: User) {
    }

    override fun fanBaoPass(user: User) {
    }

    override fun getAllFindFriendPokers(): List<Poker> {
        return emptyList()
    }

    override fun findFriend(user: User, id: Int) {
    }

    override fun drawPlayed(user: User, ids: List<Int>) {
    }

    override fun drawTake(user: User, ids: List<Int>) {
    }

    override fun getSpade7(): Poker? {
        return null
    }

    override fun playPlayed(user: User, ids: List<Int>): Boolean {
        return false
    }

    override fun playPass(user: User) {
    }

    override fun getDealerUserId(): Int {
        return -1
    }

    override fun getIntegralChange(player: Player): Int {
        return 0
    }

}

abstract class BaseRoomState(val room: Room) : RoomStateAdapter() {
    // 下面是一些和业务无关的方法实现
    override fun contains(user: User): Boolean {
        return contains(user.id)
    }

    override fun contains(userId: Int): Boolean {
        return room.players.any { it?.user?.id == userId }
    }

    override fun isFull(): Boolean {
        return room.players.all { it != null }
    }

    override fun isEmpty(): Boolean {
        return room.players.all { it == null }
    }

    override fun addPlayer(user: User) {
        for (i in 0..3) {
            if (room.players[i] == null) {
                room.players[i] = Player(user)
                break
            }
        }
    }

    override fun removePlayer(user: User) {
        for (i in 0..3) {
            if (room.players[i]?.user?.id == user.id) {
                room.players[i] = null
                break
            }
        }
    }

    override fun getSpade7(): Poker? {
        return room.pokers.find {
            it.suit == Suit.SPADE && it.getValue() == 7
        }
    }

    protected fun isAllReady(): Boolean {
        return room.players.all { it?.state == PlayerState.READY }
    }

    protected fun getSpade7Player(): Player? {
        val spade7UserId = getSpade7()?.holderUserId ?: return null
        return getPlayer(spade7UserId)
    }

    protected fun Player.isAllPokersPlayed(): Boolean {
        return this.getPokers().all { it.state != PokerState.NORMAL }
    }

    /**
     * 必须全部匹配才会返回。否则返回空集合。
     */
    protected fun Player.getPokers(ids: List<Int>): List<Poker> {
        val result = getPokers().filter { ids.contains(it.id) }
        return if (result.size != ids.size) {
            emptyList()
        } else {
            result
        }
    }

    protected fun Player.getPokers(): List<Poker> {
        return room.pokers.filter { it.holderUserId == this.user.id }
    }

    protected fun getPlayer(user: User): Player? {
        return getPlayer(user.id)
    }

    /**
     * 一轮较量中，自己是否赢牌？
     * 除了自己外，其它人没有出完的人全部pass，则自己胜出
     */
    protected fun Player.winPoker(): Boolean {
        for (player in room.players) {
            player ?: return false
            if (player.user.id == this.user.id) {// 自己
                if (player.state == PlayerState.PLAY_PASS) {
                    return false
                }
            } else {// 其它人
                if (player.completedOrder == CompletedOrder.NONE && player.state != PlayerState.PLAY_PASS) {
                    return false
                }
            }
        }
        return true
    }

    protected fun Player.nextValidPlayer(): Player? {
        val nextPlayer = this.nextPlayer()
        return if (nextPlayer?.completedOrder == CompletedOrder.NONE) {
            nextPlayer
        } else {
            nextPlayer?.nextValidPlayer()
        }
    }

    protected fun Player.nextPlayer(): Player? {
        val index = room.players.indexOfFirst {
            it?.user?.id == this.user.id
        }
        return room.players[(index + 1) % 4]
    }

    private fun getPlayer(userId: Int): Player? {
        return room.players.find { it?.user?.id == userId }
    }
}